#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/ec.h>

void tSign_sm2()
{
    unsigned char mess1[] = "20181312xieyi";     //待加密的消息
    EVP_PKEY_CTX* pctx;
    EVP_PKEY* params = NULL;
    if (!(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) {
        EVP_PKEY_CTX_free(pctx);
        return;
    }
    if (!EVP_PKEY_paramgen_init(pctx)) {
        EVP_PKEY_CTX_free(pctx);
        return;
    }

    /* 使用在obj_mac.h中定义的NID_sm2p256v1命名曲线 */
    if (!EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_sm2p256v1)) {
        EVP_PKEY_CTX_free(pctx);
        return;
    }
    params = EVP_PKEY_new();
    if (!EVP_PKEY_paramgen(pctx, &params)) {
        EVP_PKEY_CTX_free(pctx);
        EVP_PKEY_free(params);
        return;
    }

    EVP_PKEY_CTX* kctx;
    EVP_PKEY* sm2_pkey = NULL;
    if (params != NULL) {
        if (!(kctx = EVP_PKEY_CTX_new(params, NULL))) {
            EVP_PKEY_CTX_free(kctx);
            EVP_PKEY_free(params);
            return;
        }
    }
    else {
        /* 创建用于生成密钥的上下文 */
        if (!(kctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) {
            EVP_PKEY_CTX_free(kctx);
            return;
        }
    }

    if (!EVP_PKEY_keygen_init(kctx)) {
        EVP_PKEY_CTX_free(kctx);
        return;
    }

    /* 生成密钥 */
    if (!EVP_PKEY_keygen(kctx, &sm2_pkey)) {
        EVP_PKEY_CTX_free(kctx);
        EVP_PKEY_free(sm2_pkey);
        return;
    }

    //EC_KEY* sm2_pkey = EC_KEY_new_by_curve_name(NID_sm2p256v1);
    //以下是公钥加密代码
    int i;
    EVP_PKEY_CTX* ctx;
    unsigned char* out, * in;
    size_t outlen, inlen = strlen((const char*)mess1);

    ctx = EVP_PKEY_CTX_new(sm2_pkey, NULL);
    if (!ctx) {
        return;
    }
    if (EVP_PKEY_encrypt_init(ctx) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        return;
    }
    if (EVP_PKEY_encrypt(ctx, NULL, &outlen, mess1, inlen) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        printf("加密失败");
        return;
    }

    out = (unsigned char*)OPENSSL_malloc(outlen);
    if (!out) {
        EVP_PKEY_CTX_free(ctx);
        printf("malloc failure\n");
        return;
    }
    if (EVP_PKEY_encrypt(ctx, out, &outlen, mess1, inlen) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        printf("加密失败");
        return;
    }

    for (i = 0; i < (int)outlen; i++)
    {
        if (i % 16 == 0)
            printf("\n%08xH: ", i);
        printf("%02x ", out[i]);
    }
    printf("\n");


    EVP_PKEY_free(sm2_pkey);
    return;
}

int main()
{
    OpenSSL_add_all_algorithms();
    tSign_sm2();
    return 0;
}
